<template>
  <div>
    <el-row type="flex" justify="start" style="margin-bottom:20px;">
      <el-col :span="2">
        <el-button type="primary" @click="initializeSystem" v-if="!isInitialized" :loading="initializeLoading" :disabled="initDisabled">系统初始化</el-button>
        <el-button type="info" disabled v-else>系统已初始化</el-button>
      </el-col>
    </el-row>
    <el-row type="flex" justify="start">
      <el-col :span="2">
        <el-button type="primary" @click="checkSystem" :loading="isChecking">系统检测</el-button>
      </el-col>
    </el-row>
    <div class="step" v-if="resultList.length > 0">
      <el-steps direction="vertical" :active="resultList.length - 1" space="100px">
        <el-step
          v-for="(step,i) in resultList"
          :key="i"
          :title="step.stepName"
          :description="step.description"
          :status="step.status"
        ></el-step>
      </el-steps>
    </div>
  </div>
</template>

<script>
/**
 * fix - 系统初始化(20/07/16)： /init/need 接口
 * code==1 : isInitialized - 是否已经初始化，初始默认值取 false （集群配置异常时，默认为 未初始化）
 * code!=1 : initDisabled - 集群配置异常，初始化按钮不可点击
 */

import { sleep } from "@/utils";
import { globalApi, managerApi } from "@/request";
import { SUCCESS_CODE } from "@/const";
import uuid from "uuid-js";
import { mapState } from "vuex";
// 默认文字的map映射
const stepMap = {
  0: "【开始创建测试数据空间】",
  1: "【开始同步测试数据空间】",
  2: "【删除测试数据空间】"
};
// 成功情况下的map映射
const stepSuccessMap = {
  0: "【成功】:创建测试数据空间",
  1: "【成功】:同步测试数据空间",
  2: "【成功】:创建资源",
  3: "【成功】:删除资源",
  4: "【成功】:删除测试数据空间"
};
// 失败情况下的map映射
const stepFailMap = {
  0: "【失败】"
};
// 声明uuid
let UUID = "test_an";

export default {
  data() {
    return {
      isInitialized: false, // 是否已经初始化，默认 未初始化
      initDisabled: false, // 初始化按钮 是否可编辑，默认 可编辑
      initializeLoading: false,
      isChecking: false,
      smokeuser: "smokeuser",
      resultList: [],
      addUserId: "", //创建的租户/用户ID
      addResHDFSID: "", //创建HDFS资源ID
      addResHbaseID: "", //创建Hbase资源ID
      addResHiveID: "", //创建Hive资源ID
      addResYARNID: "", //创建YARN资源ID
      addResKafkaID: "" //创建Kafka资源ID
    };
  },
  beforeRouteLeave(to, from, next) {
    // 系统检测中是否确定离开？
    if (this.isChecking && to.name != "login") {
      this.$confirm("系统检测中，是否离开？").then(() => {
        next();
      });
    } else {
      next();
    }
  },
  mounted(){
    // 系统是否已经初始化
    this.initialize();
  },
  methods: {
    // 系统是否已经初始化
    initialize() {
      globalApi.isInitialize().then(res => {
        this.isInitialized = res.data;
      }).catch(error => {
        //集群资源配置异常，不能初始化
        this.initDisabled = true;
        this.$message.error(error.msg)
      })
    },
    // 系统初始化操作
    initializeSystem(){
      this.initializeLoading = true;
      globalApi.initializeOper().then(res => {
        this.initializeLoading = false;
        // 更新初始化状态
        this.isInitialized = true
        this.$message({
          message: "系统初始化成功",
          type: "success"
        })
      }).catch(err => {
        // 初始化失败，则无需更新状态
        this.initializeLoading = false;
        this.$message.error("系统初始化失败，请联系管理员")
      })
    },
    async check() {
      // 判断检测是否进行中
      this.isChecking = true;
      // 初始化列表
      this.resultList = [];
      // 生产uuid
      UUID = uuid
        .create()
        .toString()
        .substr(-12);
      // 初始化标识步骤
      let stepCount = 1;
      const splicingText = " " + this.smokeuser + " " + UUID + " ";
      try {
        // 创建&同步数据空间
        this.resultList.push({
          stepName: stepMap[0] + splicingText,
          description: "",
          status: "wait"
        });
        const param = {
          userName: UUID,
          password: UUID,
          description: "testDescription"
        };
        const addUderRes = await managerApi.addTenantTest(param);
        this.addUserId = addUderRes.data;
        stepCount = stepCount + 2; //3
        this.resultList.pop();
        this.resultList.push({
          stepName: stepMap[0] + splicingText,
          description: stepSuccessMap[0] + splicingText,
          status: "success"
        });
        this.resultList.push({
          stepName: stepMap[1] + splicingText,
          description: "",
          status: "wait"
        });
        await sleep(600);
        this.resultList.pop();
        this.resultList.push({
          stepName: stepMap[1] + splicingText,
          description: stepSuccessMap[1] + splicingText,
          status: "success"
        });
        // 创建资源（暂时）
        const createAndDeleteServicesMap = this.getServiceInfoMap(UUID);
        const installedServicesString = this.installedServices.toString();
        const serviceNames = Object.keys(createAndDeleteServicesMap).filter(
          serviceName =>
            new RegExp(serviceName, "i").test(installedServicesString)
        );
        const serviceRequestInfos = serviceNames.map(
          name => createAndDeleteServicesMap[name]
        );
        const createServiceRequests = serviceRequestInfos.map(info => {
          const { request, param } = info;
          return request(param);
        });
        this.resultList.push({
          stepName: `开始创建资源`,
          description: "",
          status: "wait"
        });
        const createServiceRes = await this.handleRequestPipline(
          createServiceRequests
        );
        this.resultList.pop();
        console.log("add", createServiceRes);
        createServiceRes.forEach((res, i) => {
          this[`addRes${serviceNames[i]}ID`] = res.data;
        });
        const nextDeleteApiInfos = [];
        for (let i = 0, len = createServiceRes.length; i < len; i++) {
          if (createServiceRes[i].code != SUCCESS_CODE) {
            this.resultList.push({
              stepName: `创建${serviceNames[i]}资源`,
              description: stepFailMap[0] + createServiceRes[i].msg,
              status: "error"
            });
          } else {
            nextDeleteApiInfos.push({
              serviceName: [serviceNames[i]],
              request: serviceRequestInfos[i]
            });
            this.resultList.push({
              stepName: `创建${serviceNames[i]}资源`,
              description: stepSuccessMap[2] + createServiceRes[i].msg,
              status: "success"
            });
          }
        }
        stepCount++; //4
        // 删除资源（暂时）
        const deleteServiceParams = this.getDeleteServiceParams();
        /**
         * 判断成功创建的资源的数组长度是不是大于0
         * 大于0在请求对应的删除资源接口
         */

        if (nextDeleteApiInfos.length > 0) {
          const deleteServiceRequests = nextDeleteApiInfos.map(info => {
            const { serviceName, request } = info;
            return request.delRequest(deleteServiceParams[serviceName]);
          });
          console.log("nextDeleteApiInfos", deleteServiceRequests);
          this.resultList.push({
            stepName: `开始删除资源`,
            description: "",
            status: "wait"
          });
          const deleteServiceRes = await this.handleRequestPipline(
            deleteServiceRequests
          );
          this.resultList.pop();
          console.log("del", deleteServiceRes);
          for (let i = 0, len = deleteServiceRes.length; i < len; i++) {
            if (deleteServiceRes[i].code != SUCCESS_CODE) {
              this.resultList.push({
                stepName: `删除${nextDeleteApiInfos[i].serviceName}资源`,
                description: stepFailMap[0] + deleteServiceRes[i].msg,
                status: "error"
              });
            } else {
              this.resultList.push({
                stepName: `删除${nextDeleteApiInfos[i].serviceName}资源`,
                description: stepSuccessMap[3] + deleteServiceRes[i].msg,
                status: "success"
              });
            }
          }
        }
        stepCount++; //5
        // 删除数据空间
        this.resultList.push({
          stepName: stepMap[2],
          description: "",
          status: "wait"
        });
        const delParam = { userId: this.addUserId, isDelResource: 0 };
        const deleteTenant = await managerApi.deleteTenantTest(delParam);
        stepCount++; //6
        this.resultList.pop();
        this.resultList.push({
          stepName: stepMap[2],
          description: stepSuccessMap[4] + splicingText,
          status: "success"
        });
        // 测试结束
        this.resultList.push({ stepName: "测试结束", status: "finish" });
        this.isChecking = false;
      } catch (res) {
        console.log("stepCount:", stepCount, res);
        // 创建测试空间失败
        if (stepCount === 1) {
          this.resultList.pop();
          this.resultList.push({
            stepName: stepMap[0] + splicingText,
            description: stepFailMap[0] + splicingText + res.msg,
            status: "error"
          });
          this.isChecking = false;
        }
        // 删除测试空间失败
        else if (stepCount === 5) {
          this.resultList.pop();
          this.resultList.push({
            stepName: stepMap[2] + splicingText,
            description: stepFailMap[0] + splicingText + res.msg,
            status: "error"
          });
          this.isChecking = false;
        }
      }
    },
    // 点击系统检测按钮
    checkSystem() {
      this.check();
    },
    // 封装资源按序请求方法
    handleRequestPipline(requests = []) {
      const totalRes = [];
      const checkEnd = function() {
        return totalRes.filter(m => !!m).length === requests.length;
      };
      return new Promise((resolve, reject) => {
        for (let i = 0, len = requests.length; i < len; i++) {
          requests[i]
            .then(res => {
              totalRes[i] = res;
              if (checkEnd()) {
                resolve(totalRes);
              }
            })
            .catch(errRes => {
              totalRes[i] = errRes;
              if (checkEnd()) {
                resolve(totalRes);
              }
            });
        }
      });
    },
    // 获取创建资源时各资源所需参数
    getServiceInfoMap(id) {
      return {
        HDFS: {
          request: managerApi.postResHdfsTest,
          delRequest: managerApi.delResHDFSTest,
          param: {
            type: 1,
            capacity: 10,
            fileNum: 10,
            url: "/public/" + "TeSt" + id,
            unit: 1
          }
        },
        Hbase: {
          request: managerApi.postResHBASETest,
          delRequest: managerApi.delHBASEResTest,
          param: { type: 1, cate: 1, spaceName: "TeSt" + id }
        },
        Hive: {
          request: managerApi.postResHIVETest,
          delRequest: managerApi.delHIVEResTest,
          param: { type: 1, cate: 1, databaseName: "TeSt" + id }
        },
        YARN: {
          request: managerApi.addResourceTest,
          delRequest: managerApi.delYARNResTest,
          // param: { id: this.addUserId, queueName: id, ratio: 0 },
          param: {
            services: [
              {
                yarn: {
                  queueName: "TeSt" + id,
                  ratio: 1
                }
              }
            ],
            uid: this.addUserId
          }
        },
        Kafka: {
          request: managerApi.postResKafkaTest,
          delRequest: managerApi.delKafkaTest,
          param: { topicName: "TeSt" + id, partitionNum: 1, replication: 1 }
        }
      };
    },
    // 获取删除资源时各资源所需参数
    getDeleteServiceParams() {
      return {
        HDFS: { keepData: 0, resourceId: this.addResHDFSID },
        Hbase: { keepData: 0, resourceId: this.addResHbaseID },
        Hive: { keepData: 0, resourceId: this.addResHiveID },
        YARN: { resourceId: (this.addResYARNID || {}).yarnId },
        Kafka: { resourceId: this.addResKafkaID }
      };
    }
  },
  computed: {
    ...mapState(["installedServices"])
  }
};
</script>

<style lang="scss" scoped>
.step {
  width: 100%;
  margin-top: 20px;
}
</style>
<style>
.el-step__description {
  height: 60px;
  overflow: auto;
}
</style>